<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<style>
		.view-container {
			height: 400px;
			width: 200px;
			border: 1px solid red;
			overflow-y: scroll;
			position: fixed;
			top: 50%;
			left: 50%;
			transform: translate(-50%, -50%);
		}
		.item-container {
			position: absolute;
			top: 0;
			left: 0;
			transition: 0;
		}
		.content-container {
			height: 0;
		}
		.item {
			height: 20px;
		}
	</style>
	<body>
		<div class="view-container">
			<div class="content-container"></div>
			<div class="item-container">
			</div>
		</div>
		<a href="https://juejin.cn/post/7301911743487590452">原文</a>
		<script>
			const data = new Array(50000).fill(0).map((_, i) => i);
			const viewHeight = 400;
			const itemHeight = 20;
			
			
			let items = null;
			const viewContainer = document.querySelector(".view-container");
			const contentContainer = document.querySelector(".content-container");
			const itemContainer = document.querySelector(".item-container");
			
			let showData = data.slice(0, 20);
			
			// 监听滚动
			viewContainer.addEventListener("scroll", (e) => {
				// 设置偏移量
				itemContainer.style.transform = `translateY(${e.target.scrollTop}px)`;
				const startIndex = Math.floor(e.target.scrollTop / itemHeight);
				// 截取数据渲染
				showData = data.slice(startIndex, startIndex + 20);
				changeShowData();
			})
			contentContainer.style.height = data.length * itemHeight + "px";
			renderDom(itemContainer);
			// 渲染元素
			function renderDom(dom) {
				let fragment = document.createDocumentFragment();
				showData.forEach(item => fragment.appendChild(createItem(item)));
				dom.appendChild(fragment);
				items = document.querySelectorAll(".item");
			}
			function createItem(item) {
				const dom = document.createElement("div");
				dom.classList.add("item");
				dom.innerText = item;
				return dom;
			}
			
			function changeShowData() {
				showData.forEach((item, i) => {
					items[i].innerText = item;
				})
			}
		</script>
	</body>
</html>